package com.gitee.qdbp.jdbc.stream;

import java.util.List;
import com.gitee.qdbp.able.jdbc.condition.DbWhere;
import com.gitee.qdbp.able.jdbc.ordering.Orderings;
import com.gitee.qdbp.jdbc.api.CrudDao;

/**
 * 递归执行对象
 *
 * @author zhaohuihua
 * @version 20210530
 */
public class RecursiveExecuteStream<T> {

    protected final CrudDao<T> dao;
    protected final String codeField;
    protected final String parentField;
    protected final List<String> startCodes;
    protected final DbWhere filterWhere;
    protected final DbWhere searchWhere;
    protected final Orderings orderings;

    RecursiveExecuteStream(CrudDao<T> dao, String codeField, String parentField, List<String> startCodes,
            DbWhere filterWhere, DbWhere searchWhere, Orderings orderings) {
        this.dao = dao;
        this.codeField = codeField;
        this.parentField = parentField;
        this.startCodes = startCodes;
        this.filterWhere = filterWhere;
        this.searchWhere = searchWhere;
        this.orderings = orderings;
    }

    /**
     * 递归查询所有子节点<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在filterWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01", "D02")
        .filterBy("tenantCode").equals("T001").end() // 租户编号
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .orderBy("sortIndex asc")
        .listChildren();
     * </pre><br>
     * ORACLE： START WITH {codeField} IN( {startCode} ) CONNECT BY PRIOR {codeField} = {parentField}<br>
     * DB2/SqlServer: 使用WITH递归<br>
     * MYSQL 8.0+/PostgreSQL: 使用WITH RECURSIVE递归<br>
     * MYSQL 8.0-: 使用存储过程RECURSIVE_LIST_CHILDREN_QUERY
     * 
     * @return 子节点列表
     */
    public List<T> listChildren() {
        return dao.listChildren(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
    }

    /**
     * 递归查询所有父节点<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在filterWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01000001", "D02000008")
        .filterBy("tenantCode").equals("T001").end() // 租户编号
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .listParents();
     * </pre><br>
     * ORACLE： START WITH {codeField} IN( {startCode} ) CONNECT BY PRIOR {codeField} = {parentField}<br>
     * DB2/SqlServer: 使用WITH递归<br>
     * MYSQL 8.0+/PostgreSQL: 使用WITH RECURSIVE递归<br>
     * MYSQL 8.0-: 使用存储过程RECURSIVE_LIST_PARENTS_QUERY
     * 
     * @return 父节点列表
     */
    public List<T> listParents() {
        return dao.listParents(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
    }

    /**
     * 递归查询所有子节点编号<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在filterWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;SysDept&gt; depts = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01", "D02")
        .filterBy("tenantCode").equals("T001").end() // 租户编号
        .searchBy("id").notIn("D01", "D02").end() // 查询子节点, 但不要包含起始编号自身
        .orderBy("sortIndex asc")
        .listChildrenCodes();
     * </pre><br>
     * ORACLE： START WITH {codeField} IN( {startCode} ) CONNECT BY PRIOR {codeField} = {parentField}<br>
     * DB2/SqlServer: 使用WITH递归<br>
     * MYSQL 8.0+/PostgreSQL: 使用WITH RECURSIVE递归<br>
     * MYSQL 8.0-: 使用存储过程RECURSIVE_LIST_PARENTS_QUERY
     * 
     * @return 子节点编号
     */
    public List<String> listChildrenCodes() {
        return dao.listChildrenCodes(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
    }

    /**
     * 递归查询所有子节点编号<br>
     * recursiveBy(codeField, parentField) 按什么字段进行递归查询<br>
     * startBy 起始编号<br>
     * filterBy 数据过滤条件, 过滤哪些数据参与递归 (如数据状态,租户编号等条件)<br>
     * searchBy 结果搜索条件 (如用户输入的查询条件) 这些条件如果放在filterWhere中将无法生成完整的树<br>
     * 注意: 查询结果包括startCode节点的自身记录, 如果不需要应在searchWhere条件排除<br>
     * <pre>
    List&lt;String&gt; parentIds = qdbcBoot.crudStream(SysDept.class)
        .recursiveBy("id", "parentId") // 按id/parentId进行递归查询
        .startBy("D01000001", "D02000008")
        .filterBy("tenantCode").equals("T001").end() // 租户编号
        .searchBy("id").notIn("D01000001", "D02000008").end() // 查询所有父节点, 但不要包含起始编号自身
        })
        .listParentCodes();
     * </pre><br>
     * ORACLE： START WITH {codeField} IN( {startCode} ) CONNECT BY PRIOR {codeField} = {parentField}<br>
     * DB2/SqlServer: 使用WITH递归<br>
     * MYSQL 8.0+/PostgreSQL: 使用WITH RECURSIVE递归<br>
     * MYSQL 8.0-: 使用存储过程RECURSIVE_LIST_PARENTS_QUERY
     * 
     * @return 父节点编号
     */
    public List<String> listParentCodes() {
        return dao.listParentCodes(startCodes, codeField, parentField, filterWhere, searchWhere, orderings);
    }
}
